#include "SimpleAudioEngine.h"
#include "APlayer.h"
#ifdef BUILD_INDEPENDENT
#include <QFileInfo>
#define FULL_PATH_FUNC(s) QFileInfo(s).absoluteFilePath().toStdString()
#else
#include "CCFileUtils.h"
#define FULL_PATH_FUNC(s) cocos2d::CCFileUtils::sharedFileUtils()->fullPathForFilename(s)
#endif

namespace CocosDenshion {
static SimpleAudioEngine*	_engine = NULL;
class MediaPlayer {
public:
	~MediaPlayer()
	{
		MediaPlayer::EffectIterator it;
		QMediaPlayer* e;
		for (it = m_emap.begin(); it != m_emap.end(); ++it) {
			e = it.value();
			e->stop();
			delete e;
		}
	}
	typedef QMap<unsigned int, QMediaPlayer*>::iterator EffectIterator;
	QMediaPlayer*	hasEffect(unsigned int s)
	{
		EffectIterator it = m_emap.find(s);
		if (it == m_emap.end())
			return NULL;
		return it.value();
	}

	QMediaPlayer* preLoad(const char* p, unsigned int* key)
	{
		std::string stds = FULL_PATH_FUNC(p);
		unsigned int s = getHashCodeByString(stds.c_str());
		QMediaPlayer* e = hasEffect(s);
		if (!e) {
			QMediaContent c(QUrl::fromLocalFile(QString::fromStdString(stds)));
			if (c.isNull())
				return NULL;
			e = new QMediaPlayer();
			e->setMedia(c);
			e->setVolume(100);
			m_emap.insert(s, e);
		}
		*key = s;
		return e;
	}

public:
	APlayer		mp;
	int		ev;
	QMap<unsigned int, QMediaPlayer*>	m_emap;
};

SimpleAudioEngine::SimpleAudioEngine()
{
	m_player = new MediaPlayer();
}

SimpleAudioEngine::~SimpleAudioEngine()
{
	if (m_player)
		delete m_player;
}

SimpleAudioEngine*SimpleAudioEngine::sharedEngine()
{
	if (!_engine)
		_engine = new SimpleAudioEngine();
	return _engine;
}

void SimpleAudioEngine::end()
{
	if (_engine) {
		delete _engine;
		_engine = NULL;
	}
}

void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
{
	m_player->mp.add(FULL_PATH_FUNC(pszFilePath));
}

void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
{
	stopBackgroundMusic(false);
	preloadBackgroundMusic(pszFilePath);
	m_player->mp.setNow(FULL_PATH_FUNC(pszFilePath));
	m_player->mp.setPosition(0);
	m_player->mp.setLoop(bLoop);
	m_player->mp.play();
}

void SimpleAudioEngine::stopBackgroundMusic(bool bReleaseData)
{
	m_player->mp.stopNow(bReleaseData);
}

void SimpleAudioEngine::pauseBackgroundMusic()
{
	m_player->mp.pause();
}

void SimpleAudioEngine::resumeBackgroundMusic()
{
	m_player->mp.play();
}

void SimpleAudioEngine::rewindBackgroundMusic()
{
	m_player->mp.setPosition(0);
}

bool SimpleAudioEngine::willPlayBackgroundMusic()
{
	return true;
}

bool SimpleAudioEngine::isBackgroundMusicPlaying()
{
	return m_player->mp.state() == APlayer::PlayingState;
}

float SimpleAudioEngine::getBackgroundMusicVolume()
{
	return (m_player->mp.volume() / 100.0f);
}

void SimpleAudioEngine::setBackgroundMusicVolume(float volume)
{
	m_player->mp.setVolume((int)(volume / 100));
}

float SimpleAudioEngine::getEffectsVolume()
{
	return m_player->ev / 100.0f;
}

void SimpleAudioEngine::setEffectsVolume(float volume)
{
	if (volume < 0.01)
		m_player->ev = 0;
	else if (volume > 1)
		m_player->ev = 100;
	else
		m_player->ev = (int)(volume * 100);
	MediaPlayer::EffectIterator it;
	QMediaPlayer* e;
	for (it = m_player->m_emap.begin(); it != m_player->m_emap.end(); ++it) {
		e = it.value();
		e->setVolume(m_player->ev);
	}
}

unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop)
{
	unsigned int r = 0;
	QMediaPlayer* e = m_player->preLoad(pszFilePath, &r);
	if (e) {
		e->media().playlist()->setPlaybackMode(bLoop ? QMediaPlaylist::CurrentItemInLoop : QMediaPlaylist::CurrentItemOnce);
		e->play();
	}
	return r;
}

void SimpleAudioEngine::pauseEffect(unsigned int nSoundId)
{
	QMediaPlayer* e = m_player->hasEffect(nSoundId);
	if (e)
		e->pause();
}

void SimpleAudioEngine::pauseAllEffects()
{
	MediaPlayer::EffectIterator it;
	QMediaPlayer* e;
	for (it = m_player->m_emap.begin(); it != m_player->m_emap.end(); ++it) {
		e = it.value();
		e->pause();
	}
}

void SimpleAudioEngine::resumeEffect(unsigned int nSoundId)
{
	QMediaPlayer* e = m_player->hasEffect(nSoundId);
	if (e && (e->state() == QMediaPlayer::PausedState))
		e->play();
}

void SimpleAudioEngine::resumeAllEffects()
{
	MediaPlayer::EffectIterator it;
	QMediaPlayer* e;
	for (it = m_player->m_emap.begin(); it != m_player->m_emap.end(); ++it) {
		e = it.value();
		if (e->state() == QMediaPlayer::PausedState)
			e->play();
	}
}

void SimpleAudioEngine::stopEffect(unsigned int nSoundId)
{
	QMediaPlayer* e = m_player->hasEffect(nSoundId);
	if (e)
		e->stop();
}

void SimpleAudioEngine::stopAllEffects()
{
	MediaPlayer::EffectIterator it;
	QMediaPlayer* e;
	for (it = m_player->m_emap.begin(); it != m_player->m_emap.end(); ++it) {
		e = it.value();
		e->stop();
	}
}

void SimpleAudioEngine::preloadEffect(const char* pszFilePath)
{
	unsigned int k;
	m_player->preLoad(pszFilePath, &k);
}

void SimpleAudioEngine::unloadEffect(const char* pszFilePath)
{
	unsigned int s = getHashCodeByString(FULL_PATH_FUNC(pszFilePath).c_str());
	QMediaPlayer* e = m_player->hasEffect(s);
	if (e) {
		e->stop();
		delete e;
		m_player->m_emap.remove(s);
	}
}

}
